package classifiers;

import weka.classifiers.functions.SMO;
import Utilities.Constants;
import data_structures.DiscreteHP;
import data_structures.ContinuousHP;
import data_structures.HPConfiguration;
import data_structures.HyperParameter;
import weka.classifiers.Evaluation;
import weka.classifiers.lazy.IBk;
import weka.core.Instances;

/**
 * SVM classifier using Weka's SMO classifier.
 */
public class GaussianSVMClassifier implements Classifier {
    
    private double gammaLower;
    private double gammaUpper;
    private double cLower;
    private double cUpper;

    public GaussianSVMClassifier(double gammaLower, double gammaUpper, 
				 double cLower, double cUpper) {
	this.gammaLower = gammaLower;
	this.gammaUpper = gammaUpper;
	this.cLower = cLower;
	this.cUpper = cUpper;
    }
    
    public double evaluateClassifier(Instances instances,
					 HPConfiguration hpConfiguration) {

	
	try {
	    double gammaVal = hpConfiguration.getHyperParameters()[0].getValue();
	    double cVal = hpConfiguration.getHyperParameters()[1].getValue();

	    String[] options = new String[14];
	    options[0] = "-C";
	    options[1] = Double.toString(cVal);
	    options[2] = "-L";
	    options[3] = "0.001";
	    options[4] = "-P";
	    options[5] = "1.0E-12";
	    options[6] = "-N";
	    options[7] = "0";
	    options[8] = "-V";
	    options[9] = "-1";
	    options[10] = "-W";
	    options[11] = "1";
	    options[12] = "-K";
	    options[13] = "weka.classifiers.functions.supportVector.RBFKernel -C 250007 -G " + 
		Double.toString(gammaVal);
	   	    
	    SMO gausSMO = new SMO();
	    gausSMO.setOptions(options);
	
	    Evaluation eval = new Evaluation(instances);
	    eval.crossValidateModel(gausSMO, instances, 10, 
				    Constants.RANDOM);
	    double accuracy = eval.pctCorrect();
	    return accuracy;
	} catch (Exception e) {
	    e.printStackTrace();
	}

	return -1;
    }

    public HPConfiguration getHPConfiguration() {
	HyperParameter[] hps = new HyperParameter[2];
	hps[0] = new ContinuousHP(gammaLower,gammaUpper,gammaLower);
	hps[1] = new ContinuousHP(cLower, cUpper, cLower);
	return new HPConfiguration(hps);
    }
}
